bounce1d.c
/* * bounceld.c * pupose animation with user controlled speed and direction * note the handler does the animation * the main program reads keyboard input * compile cc bounceld.c set_ticker.c -lcurses -o bounceld */ #include <stdio.h> #include <curses.h> #include <signal.h> #define MESSAGE "hello" #define BLANK " " int row; /* current row */ int col; /* current column */ int dir; /* where we are going */ int main() { int delay; /* bigger => slower */ int ndelay; /* new delay */ int c; /* user input */ void move_msg(int); /* handler for timer */ initscr(); crmode(); noecho(); clear(); row = 10; col = 0; dir = 1; delay = 200; move (row, col); addstr(MESSAGE); signal(SIGALRM, move_msg); set_ticker(delay); while (1){ ndelay = 0; c = getch(); if (c == 'Q') break; if (c == ' ') dir = -dir; if (c == 'f' && delay > 2) ndelay = delay / 2; if (c == 's') ndelay = delay * 2; if (ndelay > 0) set_ticker(delay = ndelay); } endwin(); return 0; } void move_msg(int signum) { signal(SIGALRM, move_msg); /* reset, just in case */ move(row, col); addstr(BLANK); col += dir; move(row, col); addstr(MESSAGE); refresh(); if (dir == -1 && col <= 0) dir = 1; else if (dir == 1 && col + strlen(MESSAGE) >= COLS) dir = -1; }
bounce2d.c
/* * bounce2d 1.0 * bounce a character (default is 'o') around the screen * defined by some parameters * user input: s slow down x component, S: slow y component * f speed up x component, F: speed y component * Q quit * blocks on read, but timer tick sends SIGALRM caught by ball_move * build: cc bounce2d.c set_ticker.c -lcurses -o bounce2d */ #include <curses.h> #include <signal.h> #include "bounce.h" struct ppball the_ball; /** the main loop **/ void set_up(); void wrap_up(); int bounce_or_lose(struct ppball *); int main() { int c; set_up(); while (((c = getchar())) != 'Q') { if (c == 'f') the_ball.x_ttm--; else if (c == 's') the_ball.x_ttm++; else if (c == 'F') the_ball.y_ttm--; else if (c == 'S') the_ball.y_ttm++; } wrap_up(); return 0; } void set_up() /* * init structure and other stuff */ { void ball_move(int); the_ball.y_pos = Y_INIT; the_ball.x_pos = X_INIT; the_ball.y_ttg = the_ball.y_ttm = Y_TIM; the_ball.x_ttg = the_ball.x_ttm = X_TIM; the_ball.y_dir = 1; the_ball.x_dir = 1; the_ball.symbol = DFL_SYMBOL; initscr(); noecho(); crmode(); signal(SIGINT, SIG_IGN); mvaddch(the_ball.y_pos, the_ball.x_pos, the_ball.symbol); refresh(); signal(SIGALRM, ball_move); set_ticker(1000 / TICKS_PER_SEC); } void wrap_up() { set_ticker(0); endwin(); } void ball_move(int signum) { int y_cur, x_cur, moved; signal(SIGALRM, SIG_IGN); x_cur = the_ball.x_pos; y_cur = the_ball.y_pos; moved = 0; if (the_ball.y_ttm > 0 && the_ball.y_ttg-- == 1){ the_ball.y_pos += the_ball.y_dir; /* move */ the_ball.y_ttg = the_ball.y_ttm; /* reset */ moved = 1; } if (the_ball.x_ttm > 0 && the_ball.x_ttg-- == 1){ the_ball.x_pos += the_ball.x_dir; /* move */ the_ball.x_ttg = the_ball.x_ttm; /* reset */ moved = 1; } if (moved){ mvaddch(y_cur, x_cur, BLANK); mvaddch(y_cur, x_cur, BLANK); mvaddch(the_ball.y_pos, the_ball.x_pos, the_ball.symbol); bounce_or_lose(&the_ball); move(LINES-1, COLS-1); refresh(); } signal(SIGALRM, ball_move); } int bounce_or_lose(struct ppball *bp) { int return_val = 0; if (bp->y_pos == TOP_ROW){ bp->y_dir = 1; return_val = 1; }else if (bp->y_pos == BOT_ROW){ bp->y_dir = -1; return_val = 1; } if (bp->x_pos == LEFT_EDGE){ bp->x_dir = 1; return_val = 1; }else if (bp->x_pos == RIGHT_EDGE){ bp->x_dir = -1; return_val = 1; } return return_val; }
bounce.h
#define BLANK ' ' #define DFL_SYMBOL 'o' #define TOP_ROW 5 #define BOT_ROW 20 #define LEFT_EDGE 10 #define RIGHT_EDGE 70 #define X_INIT 10 #define Y_INIT 10 #define TICKS_PER_SEC 50 #define Y_TIM 8 #define X_TIM 8 struct ppball { int x_ttg; // x 轴下次重画还要等待多少个计时器 int y_ttg; // y 轴下次重画还要等待多少个计时器 int x_ttm; // x 轴移动需要等待的信号间隔 int y_ttm; // y 轴移动需要等待的信号间隔 int y_pos; int x_pos; int y_dir; int x_dir; char symbol; };
bug:
bounce2d. 在移动时, x_ttm 和 y_ttm 值不一样会导致移动先移动 x/y 轴, 刷新 然后再移动另外一个轴, 给人的感觉很傻, 可以判断是否两个轴都改动了, 然后再 刷新
bounce2d1.c
/* * bounce2d 1.0 * bounce a character (default is 'o') around the screen * defined by some parameters * user input: s slow down x component, S: slow y component * f speed up x component, F: speed y component * Q quit * blocks on read, but timer tick sends SIGALRM caught by ball_move * build: cc bounce2d.c set_ticker.c -lcurses -o bounce2d */ #include <curses.h> #include <signal.h> #include "bounce.h" struct ppball the_ball; /** the main loop **/ void set_up(); void wrap_up(); int bounce_or_lose(struct ppball *); int main() { int c; set_up(); while (((c = getchar())) != 'Q') { if (c == 'f') the_ball.x_ttm--; else if (c == 's') the_ball.x_ttm++; else if (c == 'F') the_ball.y_ttm--; else if (c == 'S') the_ball.y_ttm++; } wrap_up(); return 0; } void set_up() /* * init structure and other stuff */ { void ball_move(int); the_ball.y_pos = Y_INIT; the_ball.x_pos = X_INIT; the_ball.y_ttg = the_ball.y_ttm = Y_TIM; the_ball.x_ttg = the_ball.x_ttm = X_TIM; the_ball.y_dir = 1; the_ball.x_dir = 1; the_ball.symbol = DFL_SYMBOL; the_ball.x_moved = the_ball.y_moved = false; initscr(); noecho(); crmode(); signal(SIGINT, SIG_IGN); mvaddch(the_ball.y_pos, the_ball.x_pos, the_ball.symbol); refresh(); signal(SIGALRM, ball_move); set_ticker(1000 / TICKS_PER_SEC); } void wrap_up() { set_ticker(0); endwin(); } void ball_move(int signum) { int y_cur, x_cur, moved; signal(SIGALRM, SIG_IGN); x_cur = the_ball.x_pos; y_cur = the_ball.y_pos; moved = 0; if (the_ball.y_ttm > 0 && the_ball.y_ttg-- == 1){ the_ball.y_pos += the_ball.y_dir; /* move */ the_ball.y_ttg = the_ball.y_ttm; /* reset */ the_ball.y_moved = 1; moved = 1; } if (the_ball.x_ttm > 0 && the_ball.x_ttg-- == 1){ the_ball.x_pos += the_ball.x_dir; /* move */ the_ball.x_ttg = the_ball.x_ttm; /* reset */ the_ball.x_moved = 1; moved = 1; } if (moved){ mvaddch(y_cur, x_cur, BLANK); mvaddch(y_cur, x_cur, BLANK); mvaddch(the_ball.y_pos, the_ball.x_pos, the_ball.symbol); bounce_or_lose(&the_ball); move(LINES-1, COLS-1); if (the_ball.x_moved && the_ball.y_moved){ refresh(); the_ball.x_moved = the_ball.y_moved = false; /* reset */ } } signal(SIGALRM, ball_move); } int bounce_or_lose(struct ppball *bp) { int return_val = 0; if (bp->y_pos == TOP_ROW){ bp->y_dir = 1; return_val = 1; }else if (bp->y_pos == BOT_ROW){ bp->y_dir = -1; return_val = 1; } if (bp->x_pos == LEFT_EDGE){ bp->x_dir = 1; return_val = 1; }else if (bp->x_pos == RIGHT_EDGE){ bp->x_dir = -1; return_val = 1; } return return_val; }
bounce.h
#define BLANK ' ' #define DFL_SYMBOL 'o' #define TOP_ROW 5 #define BOT_ROW 20 #define LEFT_EDGE 10 #define RIGHT_EDGE 70 #define X_INIT 10 #define Y_INIT 10 #define TICKS_PER_SEC 50 #define Y_TIM 8 #define X_TIM 8 struct ppball { int x_ttg; // x 轴下次重画还要等待多少个计时器 int y_ttg; // y 轴下次重画还要等待多少个计时器 int x_ttm; // x 轴移动需要等待的信号间隔 int y_ttm; // y 轴移动絮叨等待的信号间隔 int y_pos; int x_pos; int y_dir; int x_dir; int x_moved; int y_moved; char symbol; };
继续实现, 添加挡板 bounce2d2.c
/* * bounce2d 1.0 * bounce a character (default is 'o') around the screen * defined by some parameters * user input: s slow down x component, S: slow y component * f speed up x component, F: speed y component * Q quit * blocks on read, but timer tick sends SIGALRM caught by ball_move * build: cc bounce2d.c set_ticker.c -lcurses -o bounce2d */ #include <curses.h> #include <string.h> #include <signal.h> #include "bounce.h" struct ppball the_ball; /** the main loop **/ int flap_pos = RIGHT_EDGE / 2 - LEFT_EDGE; int old_pos; void set_up(); void wrap_up(); void move_flap(); int bounce_or_lose(struct ppball *); int main() { int c; set_up(); while (((c = getchar())) != 'Q') { if (c == 'f') the_ball.x_ttm--; else if (c == 's') the_ball.x_ttm++; else if (c == 'F') the_ball.y_ttm--; else if (c == 'S') the_ball.y_ttm++; else if (c == 'a'){ if (flap_pos > LEFT_EDGE){ old_pos = flap_pos; flap_pos -= FLAP_SEEPD; move_flap(); } }else if (c == 'd'){ if (flap_pos < RIGHT_EDGE){ old_pos = flap_pos; flap_pos += FLAP_SEEPD; move_flap(); } } } wrap_up(); return 0; } void set_up() /* * init structure and other stuff */ { void ball_move(int); the_ball.y_pos = Y_INIT; the_ball.x_pos = X_INIT; the_ball.y_ttg = the_ball.y_ttm = Y_TIM; the_ball.x_ttg = the_ball.x_ttm = X_TIM; the_ball.y_dir = 1; the_ball.x_dir = 1; the_ball.symbol = DFL_SYMBOL; the_ball.x_moved = the_ball.y_moved = false; initscr(); noecho(); crmode(); signal(SIGINT, SIG_IGN); mvaddch(the_ball.y_pos, the_ball.x_pos, the_ball.symbol); move_flap(); signal(SIGALRM, ball_move); set_ticker(1000 / TICKS_PER_SEC); } void wrap_up() { set_ticker(0); endwin(); } void move_flap() { move(BOT_ROW+1, old_pos); addstr(FLAP); move(BOT_ROW+1, flap_pos); standout(); addstr(FLAP); standend(); refresh(); } void ball_move(int signum) { int y_cur, x_cur, moved; signal(SIGALRM, SIG_IGN); x_cur = the_ball.x_pos; y_cur = the_ball.y_pos; moved = 0; if (the_ball.y_ttm > 0 && the_ball.y_ttg-- == 1){ the_ball.y_pos += the_ball.y_dir; /* move */ the_ball.y_ttg = the_ball.y_ttm; /* reset */ the_ball.y_moved = 1; moved = 1; } if (the_ball.x_ttm > 0 && the_ball.x_ttg-- == 1){ the_ball.x_pos += the_ball.x_dir; /* move */ the_ball.x_ttg = the_ball.x_ttm; /* reset */ the_ball.x_moved = 1; moved = 1; } if (moved){ mvaddch(y_cur, x_cur, BLANK); mvaddch(y_cur, x_cur, BLANK); mvaddch(the_ball.y_pos, the_ball.x_pos, the_ball.symbol); if(bounce_or_lose(&the_ball)){ signal(SIGALRM, SIG_IGN); move(LINES / 2, COLS / 2); addstr("GAME OVER"); refresh(); return; } move(LINES-1, COLS-1); if (the_ball.x_moved && the_ball.y_moved){ refresh(); the_ball.x_moved = the_ball.y_moved = false; /* reset */ } } signal(SIGALRM, ball_move); } int bounce_or_lose(struct ppball *bp) /* * 1 lose * 0 not lose */ { int return_val = 0; if (bp->y_pos == TOP_ROW){ bp->y_dir = 1; }else if (bp->y_pos == BOT_ROW){ bp->y_dir = -1; if (!(bp->x_pos >= flap_pos && bp->x_pos <= (flap_pos + (int)strlen(FLAP)))){ return_val = 1; } } if (bp->x_pos == LEFT_EDGE){ bp->x_dir = 1; }else if (bp->x_pos == RIGHT_EDGE){ bp->x_dir = -1; } return return_val; }
bounce.h
#define BLANK ' ' #define DFL_SYMBOL 'o' #define TOP_ROW 5 #define BOT_ROW 20 #define LEFT_EDGE 10 #define RIGHT_EDGE 70 #define X_INIT 10 #define Y_INIT 10 #define TICKS_PER_SEC 50 #define Y_TIM 8 #define X_TIM 8 #define FLAP " " struct ppball { int x_ttg; // x 轴下次重画还要等待多少个计时器 int y_ttg; // y 轴下次重画还要等待多少个计时器 int x_ttm; // x 轴移动需要等待的信号间隔 int y_ttm; // y 轴移动絮叨等待的信号间隔 int y_pos; int x_pos; int y_dir; int x_dir; int x_moved; int y_moved; char symbol; };